package com.example.kafka.service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Random;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.kafka.entity.Account;
import com.example.kafka.entity.User;
import com.example.kafka.repository.AccountRepository;
import com.example.kafka.repository.UserRepository;

import lombok.extern.slf4j.Slf4j;

/**
 * 有数据不一致风险的服务示例
 * 多个数据库操作未在事务中执行，可能导致数据不一致
 */
@Slf4j
@Service
public class TransactionRiskyService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private AccountRepository accountRepository;

    /**
     * 风险示例1：用户注册时创建用户和账户，但没有使用事务
     * 如果创建账户失败，用户记录会残留，导致数据不一致
     */
    public String createUserWithAccountRisky(String username, String email, String fullName) {
        log.info("开始创建用户和账户（无事务保护）: {}", username);

        try {
            // 第一步：创建用户
            User user = new User();
            user.setUsername(username);
            user.setEmail(email);
            user.setFullName(fullName);
            user.setBalance(BigDecimal.ZERO);
            user.setStatus("ACTIVE");
            user = userRepository.save(user);
            log.info("用户创建成功: {}", user.getId());

            // 模拟可能的异常情况
            if (shouldSimulateFailure()) {
                throw new RuntimeException("模拟创建账户时发生异常");
            }

            // 第二步：创建账户
            Account account = new Account();
            account.setUserId(user.getId());
            account.setAccountNumber(generateAccountNumber());
            account.setBalance(BigDecimal.ZERO);
            account.setAccountType("SAVINGS");
            account.setStatus("ACTIVE");
            account = accountRepository.save(account);
            log.info("账户创建成功: {}", account.getId());

            return "用户和账户创建成功";
        } catch (Exception e) {
            log.error("创建用户和账户失败: {}", e.getMessage());
            // 注意：这里没有回滚用户记录，导致数据不一致
            return "创建失败，但用户记录可能已残留: " + e.getMessage();
        }
    }

    /**
     * 风险示例2：转账操作没有使用事务
     * 如果扣款成功但入账失败，会导致资金丢失
     */
    public String transferMoneyRisky(Long fromUserId, Long toUserId, BigDecimal amount) {
        log.info("开始转账操作（无事务保护）: 从用户{}转账{}到用户{}", fromUserId, amount, toUserId);

        try {
            // 第一步：从源用户扣款
            User fromUser = userRepository.findById(fromUserId).orElse(null);
            if (fromUser == null) {
                return "源用户不存在";
            }
            if (fromUser.getBalance().compareTo(amount) < 0) {
                return "余额不足";
            }

            fromUser.setBalance(fromUser.getBalance().subtract(amount));
            userRepository.save(fromUser);
            log.info("从用户{}扣款成功，余额: {}", fromUserId, fromUser.getBalance());

            // 模拟可能的异常情况
            if (shouldSimulateFailure()) {
                throw new RuntimeException("模拟入账时发生异常");
            }

            // 第二步：向目标用户入账
            User toUser = userRepository.findById(toUserId).orElse(null);
            if (toUser == null) {
                return "目标用户不存在";
            }

            toUser.setBalance(toUser.getBalance().add(amount));
            userRepository.save(toUser);
            log.info("向用户{}入账成功，余额: {}", toUserId, toUser.getBalance());

            return "转账成功";
        } catch (Exception e) {
            log.error("转账操作失败: {}", e.getMessage());
            // 注意：这里没有回滚已扣款的金额，导致资金丢失
            return "转账失败，资金可能已丢失: " + e.getMessage();
        }
    }

    /**
     * 风险示例3：批量更新用户状态和账户状态，没有使用事务
     * 如果部分更新失败，会导致用户和账户状态不一致
     */
    public String batchUpdateUserStatusRisky(List<Long> userIds, String newStatus) {
        log.info("开始批量更新用户状态（无事务保护）: {} 个用户", userIds.size());

        int successCount = 0;
        int failCount = 0;

        for (Long userId : userIds) {
            try {
                // 更新用户状态
                User user = userRepository.findById(userId).orElse(null);
                if (user != null) {
                    user.setStatus(newStatus);
                    userRepository.save(user);
                    log.info("用户{}状态更新成功", userId);
                }

                // 模拟可能的异常情况
                if (shouldSimulateFailure()) {
                    throw new RuntimeException("模拟更新账户状态时发生异常");
                }

                // 更新该用户的所有账户状态
                List<Account> accounts = accountRepository.findByUserId(userId);
                for (Account account : accounts) {
                    account.setStatus(newStatus);
                    accountRepository.save(account);
                    log.info("账户{}状态更新成功", account.getId());
                }

                successCount++;
            } catch (Exception e) {
                log.error("更新用户{}状态失败: {}", userId, e.getMessage());
                failCount++;
                // 注意：这里没有回滚已更新的记录，导致状态不一致
            }
        }

        return String.format("批量更新完成，成功: %d, 失败: %d", successCount, failCount);
    }

    /**
     * 风险示例4：复杂的业务操作，涉及多个表的更新，没有使用事务
     * 如果中间步骤失败，会导致数据不一致
     */
    public String complexBusinessOperationRisky(Long userId, BigDecimal amount) {
        log.info("开始复杂业务操作（无事务保护）: 用户{}, 金额{}", userId, amount);

        try {
            // 步骤1：更新用户余额
            User user = userRepository.findById(userId).orElse(null);
            if (user == null) {
                return "用户不存在";
            }
            user.setBalance(user.getBalance().add(amount));
            userRepository.save(user);
            log.info("用户余额更新成功");

            // 模拟可能的异常情况
            if (shouldSimulateFailure()) {
                throw new RuntimeException("模拟更新账户时发生异常");
            }

            // 步骤2：更新用户的所有账户余额
            List<Account> accounts = accountRepository.findByUserId(userId);
            for (Account account : accounts) {
                account.setBalance(account.getBalance().add(amount));
                accountRepository.save(account);
                log.info("账户{}余额更新成功", account.getId());
            }

            // 模拟可能的异常情况
            if (shouldSimulateFailure()) {
                throw new RuntimeException("模拟更新用户状态时发生异常");
            }

            // 步骤3：更新用户状态
            user.setStatus("UPDATED");
            userRepository.save(user);
            log.info("用户状态更新成功");

            return "复杂业务操作完成";
        } catch (Exception e) {
            log.error("复杂业务操作失败: {}", e.getMessage());
            // 注意：这里没有回滚已执行的步骤，导致数据不一致
            return "复杂业务操作失败，数据可能不一致: " + e.getMessage();
        }
    }

    private String generateAccountNumber() {
        return "ACC" + System.currentTimeMillis() + new Random().nextInt(1000);
    }

    private boolean shouldSimulateFailure() {
        // 30%的概率模拟失败
        return new Random().nextInt(100) < 30;
    }
}
